package instruments;

import data.ConnectionPoint;
import data.NavmeshRegion;
import data.InstrumentGraphics;
import data.Params;
import java.awt.Color;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
import pathfind.GlobalPathFinder;
import pathfind.LocalPathFinder;
import pathfind.PathSmoother;

/**
 * @author Dmitry
 */
public class FullFilePathFinderInstrument extends AbstractPolygonInstrument {
    private NavmeshRegion p1;
    private NavmeshRegion p2;
    private Point point1 = new Point();
    private Point point2 = new Point();
    private List<NavmeshRegion> globalPathes;
    private List<List<Point>> localPathes;

    @Override
    public void mouseDown(int x, int y, int modifiers) {
        super.mouseDown(x, y, modifiers);
        NavmeshRegion p = trySelect(x, y);
        if (p == null) {
            return;
        }

        if (isLeftDown(modifiers)) {
            p1 = p;
            p1.getIndexOfCell(x, y, point1);
        }

        if (isRightDown(modifiers)) {
            p2 = p;
            p2.getIndexOfCell(x, y, point2);
        }

        localPathes = new ArrayList<>();
        globalPathes = null;

        if (p1 != null && p2 != null) {
            clearAffectance();
            GlobalPathFinder finder = new GlobalPathFinder(p2);
            List<NavmeshRegion> globalPath = finder.compute(p1);
            if (globalPath != null) {
                pathFind(globalPath);
            }
        }

        redraw();
    }

    private void pathFind(List<NavmeshRegion> globalPath) {
        globalPathes = globalPath;
        Point pStart = point1;
        Point pEnd = null;
        boolean endPointDetermined = false;
        if (globalPath.size() == 1) {
            LocalPathFinder localPathFinder = new LocalPathFinder(point2, globalPath.get(0));
            List<Point> computedPath = localPathFinder.computeWithFallback(point1);
            PathSmoother smoother = new PathSmoother(globalPath.get(0), computedPath);
            computedPath = smoother.smooth();
            localPathes.add(computedPath);
        } else {
            for (int i = 0; i < globalPath.size(); i++) {
                ConnectionPoint cp = null;
                NavmeshRegion firstPolygon = globalPath.get(i);
                NavmeshRegion secondPolygon;
                if ((i) == globalPath.size() - 1) {
                    pEnd = point2;
                    endPointDetermined = true;
                } else {
                    secondPolygon = globalPath.get(i + 1);
                    cp = firstPolygon.getConnection().get(secondPolygon).selectRandomConnectionPoint();
                }


                if (endPointDetermined == false) {
                    pEnd = cp.getP1();
                }

                LocalPathFinder localPathFinder = new LocalPathFinder(pEnd, firstPolygon);
                List<Point> computedPath = localPathFinder.computeWithFallback(pStart);

                PathSmoother smoother = new PathSmoother(firstPolygon, computedPath);
                computedPath = smoother.smooth();
                localPathes.add(computedPath);
                if (cp != null) {
                    pStart = cp.getP2();
                }

                endPointDetermined = false;
                if (!localPathFinder.isFullPathCalculated()) {
                    break;
                }
            }
        }
    }

    @Override
    public void onDraw(InstrumentGraphics g) {
        super.onDraw(g);
        if (p1 != null) {
            g.setColor(Color.RED);
            p1.draw(g);
        }

        if (p2 != null) {
            g.setColor(Color.CYAN);
            p2.draw(g);
        }
        g.setColor(Color.WHITE);
        if (globalPathes != null && !globalPathes.isEmpty() && localPathes != null) {
            for (int j = 0; j < localPathes.size(); j++) {
                NavmeshRegion polygon = globalPathes.get(j);
                List<Point> localPath = localPathes.get(j);
                for (int i = 0; i < localPath.size() - 1; i++) {
                    double x1 = polygon.getX() + localPath.get(i).x * Params.CELL_SIZE + Params.CELL_SIZE / 2;
                    double y1 = polygon.getY() + localPath.get(i).y * Params.CELL_SIZE + Params.CELL_SIZE / 2;
                    double x2 = polygon.getX() + localPath.get(i + 1).x * Params.CELL_SIZE + Params.CELL_SIZE / 2;
                    double y2 = polygon.getY() + localPath.get(i + 1).y * Params.CELL_SIZE + Params.CELL_SIZE / 2;
                    g.drawLine(x1, y1, x2, y2);
                }
            }
        }
    }
}
